package com.ibm.cps.sql.expression.function;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.reflections.Reflections;

import com.ibm.cps.processors.AbstractProcessor;
import com.ibm.cps.processors.DFTProcessor;
import com.ibm.cps.processors.Info;
import com.ibm.cps.processors.VarianceProcessor;
import com.ibm.cps.sql.expression.function.scalar.CosFunc;
import com.ibm.cps.sql.expression.function.scalar.ExpressionFunction;
import com.ibm.cps.sql.expression.function.scalar.LogFunc;
import com.ibm.cps.sql.expression.function.scalar.SinFunc;
import com.ibm.cps.sql.expression.function.scalar.SqrtFunc;
import com.ibm.util.ErrorCode;
import com.ibm.util.exception.CPSException;

public class FunctionRegister {
	private static Map<String, ExpressionFunction> scalarFunctions = new HashMap<>();
	private static Map<String, Class<?>> vectorFunctions = new HashMap<>();
	private static Logger logger = Logger.getLogger(FunctionRegister.class);

	//TODO: mind to lower case
	static{
		scalarFunctions.put("sqrt", new SqrtFunc());
		scalarFunctions.put("sin", new SinFunc());
		scalarFunctions.put("cos", new CosFunc());
		scalarFunctions.put("log", new LogFunc());

//		vectorFunctions.put("dft", DFTProcessor.class);
//		vectorFunctions.put("variance", VarianceProcessor.class);
		Reflections reflections = new Reflections("com.ibm");
		Set<Class<? extends AbstractProcessor>> processors = reflections.getSubTypesOf(AbstractProcessor.class);
		for(Class<? extends AbstractProcessor> processor : processors){
			// skip the abstract AbstractProcessor's sub class.
			if(Modifier.isAbstract(processor.getModifiers())){
				continue;
			}
			if(processor.isAnnotationPresent(Info.class)){
				Info info = processor.getAnnotation(Info.class);
				if(info.Type() != Info.ProcessorType.Vector){
					continue;
				}
				if(vectorFunctions.containsKey(info.Name())){
					String message = info.Name() + " already exists, error happened in: " + processor.getName();
					logger.warn(message);
				}
				vectorFunctions.put(info.Name(),processor);
			}
		}
	}

	public static ExpressionFunction findScalarFunction(String name){
		return scalarFunctions.get(name.toLowerCase());
	}

	public static Class<?> findVectorFunction(String name){
		return vectorFunctions.get(name);
	}
	public static void main(String[] args){
		
		FunctionRegister x  = new FunctionRegister();
		System.out.println("x");
	}
}
